/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package skytestarmor;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.log4j.Logger;
import ru.jSkyRoom.factory.LeveledEntryFactory;
import ru.jSkyRoom.finder.FinderByEdidFacade;
import ru.jSkyRoom.interfaces.JSkyMod;
import ru.jSkyRoom.interfaces.major.Armor;
import ru.jSkyRoom.interfaces.major.LeveledItemList;
import ru.jSkyRoom.interfaces.major.Major;
import ru.jSkyRoom.interfaces.sub.JSkyLeveledEntry;
import ru.jSkyRoom.manager.ModManager;

/**
 *
 * @author alx
 */
public class LeveledOutfits {

    /*Здесь разбираются файлы задающие обмундирование НПС.
     * Наименование файла соответвует LeveledItem-у объединяющему все  возможные варианты одежду конкретной группы НПС
     * Внутри файла содержится описание LeveledItem, формирующих сеты.
     * LeveledItem отделены друг от друга пустой строкой
     * Первая строка содержит наименование LeveledItem
     * все последующие содержа наимеонвания(Editor ID) брони и других LeveledItem входящих в этот LeveledItem
     * Если в строке наименования LeveledItem после наименования через пробел стоит число, то это LeveledItem верхнего уровня, он будет включен в LeveledItem
     * Саможе число указывает к какой уровневой группе принадлежит этот LeveledItem(то есть с какого уровня начнет встречаться)
     *
     */
    //private Map<String, LVLI> allTopLeveledItem = new HashMap<String, LVLI>();
    //private Map<String, ArrayList<String>> heigthLeveledItemForOutfit_list = new HashMap<String, ArrayList<String>>();
    //private Map<String, Integer> heigthLeveledItemLevel = new HashMap<>();
    private int[] lvlArray = {1, 9, 17, 25, 37, 43};
    // private ArrayList<RecordNameLvlEntituList> topOutfitNodes = new ArrayList<>();
    public Map<String, RecordNameLvlEntituList> subSetNodes = new HashMap<>();
    private static final Logger logger = Logger.getLogger(GeneratorOfKeywordEnchantmentsLinks.class.getName());
    //private String workDir = ".";
    private String workDir = "C:\\Steam\\SteamApps\\common\\Skyrim\\KR_settings";

    LeveledOutfits(JSkyMod libMods, String workDir_in) {
        workDir = workDir_in;
        ArrayList<RecordNameLvlEntituList> topOutfitNodes = readOutfits();
        fullSubSetNodes();
        createLeveledStructure(topOutfitNodes, libMods);

    }

    private void createLeveledStructure(ArrayList<RecordNameLvlEntituList> topOutfitNodes, JSkyMod libMods) {
        LeveledItemList heigthLeveledItemFID;
        for (RecordNameLvlEntituList topNode : topOutfitNodes) {
            createTree(topNode.entityNames, topNode.name, libMods);
        }

    }

    private Major createLvlLeveledItemNode(Integer lvl, String in_nodeName, JSkyMod libMods) {
        String[] words = in_nodeName.split(" ");
        String nodeName;
        Integer chans;

        RecordNameLvlEntituList tmp_node = createNodeHeadByName(in_nodeName);

        RecordNameLvlEntituList leveledItem_list = subSetNodes.get(tmp_node.name);
        if ((lvl < tmp_node.MinLvl) || (lvl > tmp_node.MaxLvl)) {
            return null;
        } else {
            if (leveledItem_list == null) {
                //это броня
                return createNodeFromArmor(lvl, tmp_node.name, libMods, tmp_node.chanceNone, tmp_node.isRobe);
            } else {
                //это список
                return createNodeFromLeveledItem(lvl, leveledItem_list.name, libMods, leveledItem_list.entityNames, tmp_node.chanceNone, leveledItem_list.isUseAll);
            }
        }
    }

    private Major createNodeFromArmor(Integer lvl, String nodeName, JSkyMod modLibs, Integer chanceNone, Boolean isRobe) {
        //LBenchArmorS_Valkyrie_Gloves_04
        Armor armor = getFinder().findArmor(nodeName);
        if (armor == null) {
            LeveledItemList armorGroup = getFinder().findLeveledItemList(nodeName);
            if (armorGroup == null) {
                logger.error("Броня " + nodeName + " из файлов каталога 'Outfit_sets'  не найдена");
                return null;
            } else {
                return armorGroup;
            }

            //ошибка
        }
        /*
         ARMO armorNoPlayer = (ARMO) patc.getArmors().get(nodeName+"_NoPlayer");
         if(armorNoPlayer==null){
         armorNoPlayer = (ARMO) SPGlobal.getGlobalPatch().getArmors().get(nodeName+"_NoPlayer");
         if(armorNoPlayer==null){
         armorNoPlayer = (ARMO) SPGlobal.getGlobalPatch().makeCopy(armor, nodeName+"_NoPlayer");
         armorNoPlayer.set(MajorRecord.MajorFlags.Deleted, isRobe);
         }

         }
         */

        String personItemName = armor.getEDID().substring(3);//Valkyrie_Gloves

        String armorGroupName;
        /*
         if (isRobe) {
         armorGroupName = "LBenchRobeS_" + personItemName + "_0" + String.valueOf(lvl);
         } else {
         armorGroupName = "LBenchArmorS_" + personItemName + "_0" + String.valueOf(lvl);
         }
         */
        armorGroupName = "LBenchArmorS_" + personItemName + "_0" + String.valueOf(lvl);

        LeveledItemList enchArmorGroup = getFinder().findLeveledItemList(armorGroupName);
        if ((enchArmorGroup == null) && !isRobe) {
            enchArmorGroup = getFinder().findLeveledItemList("LBenchArmorS_" + personItemName + "_0" + String.valueOf(lvl));
        }

        if (chanceNone == 0) {
            if (enchArmorGroup == null) {
                return armor;
            } else {
                String lvlNodeName = "lvl" + String.valueOf(lvl) + "_" + nodeName;
                LeveledItemList armorGroup = getFinder().findLeveledItemList(lvlNodeName);
                if (armorGroup == null) {
                    LeveledItemList base = getFinder().findLeveledItemList("LItem_LB__Gloves");
                    armorGroup = getActiveMod().makeCopy(base, lvlNodeName);
                    fullEndNodeArmor(isRobe, enchArmorGroup, armorGroup, armor, modLibs);
                }
                return armorGroup;
            }
        } else {
            String chansLvlNodeName = "lvl" + String.valueOf(lvl) + "_" + nodeName + "_Ch" + chanceNone.toString();
            LeveledItemList armorGroup = getFinder().findLeveledItemList(chansLvlNodeName);
            if (armorGroup == null) {
                String ChansNone_Template = "ChansNone_Template_" + chanceNone.toString();
                //String ChansNone_Template = "ChansNone_Template_70";
                LeveledItemList templChansNone = getFinder().findLeveledItemList(ChansNone_Template);
                if (templChansNone == null) {

                    Integer chance = 100 - chanceNone;
                    logger.error("Шанс " + chance + " не предусмотрен. Ишется шаблон '" + ChansNone_Template + "'");
                    return null;

                    //String lvlNodeName = "lvl" + String.valueOf(lvl) + "_" + nodeName;
                    //armorGroup = (LVLI) SPGlobal.getGlobalPatch().makeCopy(modLibs.getLeveledItems().get("LItem_LB__Gloves"), lvlNodeName);
                } else {
                    armorGroup = getActiveMod().makeCopy(templChansNone, chansLvlNodeName);
                }

                if (enchArmorGroup == null) {
                    JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(armor, 1, 1);
                    armorGroup.addEntry(leveledEntry);
                } else {
                    fullEndNodeArmor(isRobe, enchArmorGroup, armorGroup, armor, modLibs);
                }
            }
            return armorGroup;

        }

    }

    private Major createNodeFromLeveledItem(Integer lvl, String nodeName, JSkyMod patc, ArrayList<String> leveledItem_list, Integer chans, Boolean useAll) {
        String chansLvlNodeName;
        if (chans > 0) {
            chansLvlNodeName = "lvl" + String.valueOf(lvl) + "_" + nodeName + "_Ch" + chans.toString();
        } else {
            chansLvlNodeName = "lvl" + String.valueOf(lvl) + "_" + nodeName;
        }
        LeveledItemList chansArmorGroup = getFinder().findLeveledItemList(chansLvlNodeName);
        if (chansArmorGroup == null) {
            if (useAll) {
                LeveledItemList base = getFinder().findLeveledItemList("LB_Temp_UseAll");
                chansArmorGroup = getActiveMod().makeCopy(base, chansLvlNodeName);
            } else {
                LeveledItemList base = getFinder().findLeveledItemList("LItem_LB__Gloves");
                chansArmorGroup = getActiveMod().makeCopy(base, chansLvlNodeName);
            }
            for (String entryName : leveledItem_list) {
                Major childNode = createLvlLeveledItemNode(lvl, entryName, patc);
                if (childNode != null) {
                    JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(childNode, 1, 1);
                    chansArmorGroup.addEntry(leveledEntry);
                }
            }
        }

        return chansArmorGroup;
    }

    private void fullEndNodeArmor(Boolean isRobe, LeveledItemList enchArmorGroup, LeveledItemList fullingArmorGroup, Armor armor, JSkyMod modLibs) {

        if (armor.getEDID().endsWith("_NoPlayer")) {
            JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(armor, 1, 1);
            fullingArmorGroup.addEntry(leveledEntry);
            return;
        }

        Armor noPlayerArmor = getFinder().findArmor(armor.getEDID() + "_NoPlayer");
        if (noPlayerArmor == null) {
            noPlayerArmor = armor;
        }

        if (isRobe) {
            for (JSkyLeveledEntry existLeveledEntry : enchArmorGroup) {
                JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(existLeveledEntry.getItem(), 1, 1);
                fullingArmorGroup.addEntry(leveledEntry);
                JSkyLeveledEntry armorLeveledEntry = getLeveledEntryFactory().create(armor, 1, 1);
                fullingArmorGroup.addEntry(armorLeveledEntry);
            }
            int enchChet = enchArmorGroup.getEntries().size();
            int noPlayerChet = enchChet * 4 / 10;
            for (int i = 0; i < noPlayerChet; i++) {
                JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(noPlayerArmor, 1, 1);
                fullingArmorGroup.addEntry(leveledEntry);
            }

        } else {
            for (int i = 1; i < 12; i++) {
                JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(noPlayerArmor, 1, 1);
                fullingArmorGroup.addEntry(leveledEntry);
            }
            for (int i = 1; i < 7; i++) {
                JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(armor, 1, 1);
                fullingArmorGroup.addEntry(leveledEntry);
            }
            JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(enchArmorGroup, 1, 1);
            fullingArmorGroup.addEntry(leveledEntry);
        }

    }

    private ArrayList<RecordNameLvlEntituList> readOutfits() {
        RecordNameLvlEntituList topNode = new RecordNameLvlEntituList();
        ArrayList<RecordNameLvlEntituList> in_topOutfitNodes = new ArrayList<>();

        try {
            BufferedReader myfile = new BufferedReader(new FileReader(workDir + "Outfit_sets\\Outfits.txt"));

            Boolean inSet = false;
            for (String line = myfile.readLine(); line != null; line = myfile.readLine()) {
                if (line.trim().equals("")) {
                    if (inSet) {
                        inSet = false;
                        //завершающие действия инициализации LeveledItem
                    }
                } else {
                    if (inSet) {
                        //вставляем новый элемент в LeveledItem
                        topNode.entityNames.add(line);
                    } else {
                        //это новый LeveledItem
                        inSet = true;
                        String[] words = line.split(" ");
                        topNode = new RecordNameLvlEntituList();
                        topNode.name = words[0];
                        topNode.entityNames = new ArrayList<String>();
                        in_topOutfitNodes.add(topNode);
                    }
                }

            }
//leveledItems = (LVLI) SPGlobal.getGlobalPatch().getLeveledItems().get(nameLeveledItems);

        } catch (FileNotFoundException ex) {
            logger.error("Файл" + workDir + "Outfit_sets\\Outfits.txt  не найден", ex);
        } catch (IOException ex) {
            logger.error("Ошибка ввода вывода в файле " + workDir + "Outfit_sets\\Outfits.txt", ex);
        }

        return in_topOutfitNodes;
    }

    private void fullSubSetNodes() {
        RecordNameLvlEntituList topNode = new RecordNameLvlEntituList();
        ArrayList<RecordNameLvlEntituList> in_topOutfitNodes = new ArrayList<>();

        try {
            BufferedReader myfile = new BufferedReader(new FileReader(workDir + "Outfit_sets\\SubLeveledItem.txt"));

            Boolean inSet = false;
            for (String line = myfile.readLine(); line != null; line = myfile.readLine()) {
                if (line.trim().equals("")) {
                    if (inSet) {
                        inSet = false;
                        //завершающие действия инициализации LeveledItem
                    }
                } else {
                    if (inSet) {
                        //вставляем новый элемент в LeveledItem
                        topNode.entityNames.add(line);
                    } else {
                        //это новый LeveledItem
                        inSet = true;
                        topNode = createNodeHeadByName(line);
                        topNode.entityNames = new ArrayList<String>();
                        subSetNodes.put(topNode.name, topNode);
                    }
                }

            }
//leveledItems = (LVLI) SPGlobal.getGlobalPatch().getLeveledItems().get(nameLeveledItems);

        } catch (FileNotFoundException ex) {
            logger.error("Файл" + workDir + "Outfit_sets\\SubLeveledItem.txt  не найден", ex);
        } catch (IOException ex) {
            logger.error("Ошибка ввода вывода в файле " + workDir + "Outfit_sets\\SubLeveledItem.txt", ex);
        }

    }

    private void createTree(ArrayList<String> EntityNames, String outfitGroupName, JSkyMod libMods) {
        LeveledItemList outfitGroup = getFinder().findLeveledItemList(outfitGroupName);
        Major lvlSet;
        RecordNameLvlEntituList tmp_node;

        if (outfitGroup == null) {
            //ошибка этот это группа должна быть, так как является точкой связи
        } else {
            getActiveMod().addMajor(outfitGroup);
            for (Iterator<JSkyLeveledEntry> iterator = outfitGroup.iterator(); iterator.hasNext();) {
                iterator.next();
                iterator.remove();
            }

            for (String setName : EntityNames) {
                tmp_node = createNodeHeadByName(setName);
                for (Integer lvl = tmp_node.MinLvl; lvl <= tmp_node.MaxLvl; lvl++) {
                    lvlSet = createLvlLeveledItemNode(lvl, setName, libMods);
                    if (lvlSet == null) {
                        logger.error("Не создан LeveledItem " + EntityNames + " входящий верхний уровень." + outfitGroupName);

                        //ошибка
                    } else {

                        JSkyLeveledEntry leveledEntry = getLeveledEntryFactory().create(lvlSet, lvlArray[lvl - 1], 1);
                        outfitGroup.addEntry(leveledEntry);
                    }
                }
            }
        }

    }

    public RecordNameLvlEntituList createNodeHeadByName(String nodeName) {
        String[] words = nodeName.split(" ");
        RecordNameLvlEntituList node = new RecordNameLvlEntituList();
        node.name = words[0];
        node.entityNames = new ArrayList<>();
        for (int i = 1; i < words.length; i++) {
            if (words[i].toUpperCase().equals("ROBES")) {
                node.isRobe = true;
            } else if (words[i].toUpperCase().equals("USEALL")) {
                node.isUseAll = true;
                /* } else if (words[i].toUpperCase().equals("NOLEVELED")) {
                 node.noLeveled = true;
                 */            } else if (words[i].toUpperCase().equals("BATTLEMAG")) {
                node.isRobe = true;
            } else if (words[i].startsWith("Chance=")) {
                node.chanceNone = 100 - Integer.valueOf(words[i].substring("Chance=".length()));
            } else if (words[i].startsWith("MimLvl=")) {
                try {
                    node.MinLvl = Integer.valueOf(words[i].substring("MimLvl=".length()));
                } catch (Exception ex) {
                    logger.error("Ошибка преобразования числовой части " + words[i], ex);
                }
            } else if (words[i].startsWith("MaxLvl=")) {
                try {
                    node.MaxLvl = Integer.valueOf(words[i].substring("MaxLvl=".length()));
                } catch (Exception ex) {
                    logger.error("Ошибка преобразования числовой части " + words[i], ex);
                }
            } else {
                if (!words[i].trim().isEmpty()) {
                    logger.error("Обнаружен не распознаваемый парамерт " + words[i] + " в строке " + nodeName);
                }
                /*try {
                 if (!words[i].trim().isEmpty()) {
                 node.minLevelGroup = Integer.valueOf(words[i]);
                 }
                 } catch (Exception ex) {
                 String hj = words[i];
                 logger.error("Ошибка преобразования числовой части " + words[i], ex);
                 }*/
            }
        }
        if (node.MinLvl == -1) {
            node.MinLvl = 1;
        }
        if (node.MaxLvl == 1000) {
            node.MaxLvl = 6;
        }
        return node;
    }

    Map<String, RecordNameLvlEntituList> readSubSets(JSkyMod libMods, LeveledOutfits leveledOutfits) {
        Map<String, RecordNameLvlEntituList> in_subSetNodes = new HashMap<>();
        try {
            BufferedReader myfile = new BufferedReader(new FileReader(workDir + "\\Outfit_sets\\SubLeveledItem.txt"));
            Boolean inSet = false;
            ArrayList<String> listNames = new ArrayList<>();
            ArrayList<String> EntityNames = new ArrayList<>();
            RecordNameLvlEntituList topNode = new RecordNameLvlEntituList();
            for (String line = myfile.readLine(); line != null; line = myfile.readLine()) {
                if (line.trim().equals("")) {
                    if (inSet) {
                        inSet = false;
                    }
                } else {
                    if (inSet) {
                        topNode.entityNames.add(line);
                    } else {
                        inSet = true;
                        topNode = leveledOutfits.createNodeHeadByName(line);
                        in_subSetNodes.put(topNode.name, topNode);
                    }
                }
            }
        } catch (FileNotFoundException ex) {
            //Logger.getLogger(LeveledOutfits.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            // Logger.getLogger(LeveledOutfits.class.getName()).log(Level.SEVERE, null, ex);
        }
        return in_subSetNodes;
    }

    protected FinderByEdidFacade getFinder() {
        return FinderByEdidFacade.create();
    }

    protected JSkyMod getActiveMod() {
        return ModManager.getInstance().getActiveMod();
    }

    protected LeveledEntryFactory getLeveledEntryFactory() {
        return LeveledEntryFactory.create();
    }
}
